package com.mall.order.services;

import com.mall.order.OrderCoreService;
import com.mall.order.dal.entitys.*;
import com.mall.order.dal.persistence.*;
import com.mall.order.dto.CreateOrderResponse;
import com.mall.order.dto.QueryDormByOrderDto;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.dto.IUserInfoDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

/**
 *
 */
@Transactional(rollbackFor = Exception.class)
@Slf4j
@Component
@Service(cluster = "failfast")
public class OrderCoreServiceImpl implements OrderCoreService {

    @Autowired
    UserMapper userMapper;
    @Autowired
    UserInfoMapper userInfoMapper;
    @Autowired
    DormMapper dormMapper;
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    OrderDetailMapper orderDetailMapper;
    @Autowired
    UserDormAssociateMapper userDormAssociateMapper;
    @Autowired
    BuildingRoomMapper buildingRoomMapper;

    private static final int MAX_MATE_NUM = 3;

    @Override
    public CreateOrderResponse createOrder(Map<String, Object> request) {

        CreateOrderResponse response = new CreateOrderResponse();

        try {
            //参数校验
            requestCheck(request);

            //业务逻辑
            //封装存储学号验证码的的map
            HashMap<String, String> teammatesMap = new HashMap<>();
            for (int i = 0; i < MAX_MATE_NUM; i++) {
                String otherStuNo = (String) request.get("otherStuNo" + i);
                String otherAuthCode = (String) request.get("otherAuthCode" + i);
                if (otherStuNo != null && !"".equals(otherStuNo) && otherAuthCode != null && !"".equals(otherAuthCode)) {
                    teammatesMap.put(otherStuNo, otherAuthCode);
                }
            }

            Integer userId = (Integer) request.get("userId");
            Integer buildingId = Integer.parseInt((String) request.get("buildingId"));
            String selfStudentNo = (String) request.get("selfStudentNo");
            String selfAuthCode = (String) request.get("selfAuthCode");
            //String teammatesMap1 = (String) request.get("teammatesMap");

            //首先检测是否已经选过宿舍
            Example userInfoExample = new Example(UserInfo.class);
            userInfoExample.createCriteria()
                    .andEqualTo("stuNo", selfStudentNo)
                    .andEqualTo("isDeleted", 0);
            List<UserInfo> userInfos = userInfoMapper.selectByExample(userInfoExample);
            if (userInfos == null || userInfos.size() != 1) {
                response.setCode(SysRetCodeConstants.REQUEST_CHECK_FAILURE.getCode());
                response.setMsg(SysRetCodeConstants.REQUEST_CHECK_FAILURE.getMessage());
                return response;
            }
            UserInfo userInfo = userInfos.get(0);
            if (userInfo.getIsChosen() == 1) {
                response.setCode(SysRetCodeConstants.USER_IS_CHOSEN.getCode());
                response.setMsg(SysRetCodeConstants.USER_IS_CHOSEN.getMessage());
                return response;
            }

            for (String stuNo : teammatesMap.keySet()) {
                Example otherUserinfoExample = new Example(UserInfo.class);
                otherUserinfoExample.createCriteria()
                        .andEqualTo("stuNo", stuNo)
                        .andEqualTo("isDeleted", 0);
                List<UserInfo> userInfos1 = userInfoMapper.selectByExample(otherUserinfoExample);
                if (userInfos1 == null || userInfos1.size() != 1) {
                    response.setCode(SysRetCodeConstants.REQUEST_CHECK_FAILURE.getCode());
                    response.setMsg(SysRetCodeConstants.REQUEST_CHECK_FAILURE.getMessage());
                    return response;
                }
                UserInfo userInfo1 = userInfos1.get(0);
                if (userInfo1.getIsChosen() == 1) {
                    response.setCode(SysRetCodeConstants.USER_IS_CHOSEN.getCode());
                    response.setMsg(SysRetCodeConstants.USER_IS_CHOSEN.getMessage());
                    return response;
                }
            }


            //存储性别的set
            HashSet<String> genderSet = new HashSet<>();

            //首先验证自己输入的学号、认证码与数据库中保存的是否一致
            IUserInfoDto userInfoDto = userMapper.selectUserInfoByUserId(userId);
            genderSet.add(userInfoDto.getGender());
            if (!selfStudentNo.equals(userInfoDto.getStudentNo()) ||
                    !selfAuthCode.equals(userInfoDto.getVerifyCode())) {
                response.setCode(SysRetCodeConstants.REQUEST_CHECK_FAILURE.getCode());
                response.setMsg(SysRetCodeConstants.REQUEST_CHECK_FAILURE.getMessage());
                return response;
            }

            //验证组队队友的学号与验证码
            for (Map.Entry<String, String> entry : teammatesMap.entrySet()) {
                IUserInfoDto infoDto = userMapper.selectUserInfoByStuNo(entry.getKey());
                genderSet.add(infoDto.getGender());
                if (!entry.getKey().equals(infoDto.getStudentNo()) ||
                        !entry.getValue().equals(infoDto.getVerifyCode())) {
                    response.setCode(SysRetCodeConstants.REQUEST_CHECK_FAILURE.getCode());
                    response.setMsg(SysRetCodeConstants.REQUEST_CHECK_FAILURE.getMessage());
                    return response;
                }
            }

            //检测同一表单中的所有申请人性别是否一致
            if (genderSet.size() != 1) {
                //说明申请的同住人列表中存在性别不一致的问题
                response.setCode(SysRetCodeConstants.GENDER_CHECK_FAILURE.getCode());
                response.setMsg(SysRetCodeConstants.GENDER_CHECK_FAILURE.getMessage());
                return response;
            }

            //检测所选宿舍楼是否还有空余床位和宿舍
            //参数依次为楼id、性别、表单申请总人数
            List<QueryDormByOrderDto> queryDormByOrderDtos = dormMapper.selectDormInfoByOrder(buildingId, userInfoDto.getGender(), teammatesMap.size() + 1);
            if (queryDormByOrderDtos == null || queryDormByOrderDtos.size() == 0) {
                response.setCode(SysRetCodeConstants.ROOM_CHECK_FAILURE.getCode());
                response.setMsg(SysRetCodeConstants.ROOM_CHECK_FAILURE.getMessage());
                return response;
            }

            //随机分配一间宿舍
            int index = (int) (Math.random() * queryDormByOrderDtos.size());
            QueryDormByOrderDto allocatedRoom = queryDormByOrderDtos.get(index);

            //插入订单表、订单详情表、用户宿舍关联表
            //插入订单表
            Order order = new Order();
            order.setUid(userId);
            order.setBuildingId(buildingId);
            order.setGender(userInfoDto.getGender());
            order.setPeopleNo(teammatesMap.size() + 1);
            order.setIsSuccess(1);
            order.setCreateTime(new Date());
            order.setIsDel(0);
            int affectedRows1 = orderMapper.insertUseGeneratedKeys(order);
            Integer orderId = order.getId();

            //插入订单详情表
            OrderDetail orderDetail = new OrderDetail();
            //shared_id由同选宿舍人的学号拼成，中间以空格隔开
            Set<String> strings = teammatesMap.keySet();
            String sharedId = selfStudentNo;
            for (String studentNo : strings) {
                sharedId = sharedId + " " + studentNo;
            }
            orderDetail.setSharedId(sharedId);
            orderDetail.setOrderId(orderId);
            String orderCode = UUID.randomUUID().toString();
            orderDetail.setOrderCode(orderCode);
            orderDetail.setIsDel(0);
            int affectedRows2 = orderDetailMapper.insertUseGeneratedKeys(orderDetail);


            int affectedRows31 = 0, affectedRows32 = 0;
            UserDormAssociate userDormAssociate = new UserDormAssociate();
            userDormAssociate.setUid(userId);
            userDormAssociate.setOrderId(orderId);
            userDormAssociate.setRoomName(allocatedRoom.getRoomName());
            userDormAssociate.setStuNo(selfStudentNo);
            userDormAssociate.setCreateTime(new Date());
            userDormAssociate.setUpdateTime(new Date());
            userDormAssociate.setIsDel(0);
            affectedRows31 = userDormAssociateMapper.insertUseGeneratedKeys(userDormAssociate);

            for (String stuNo : teammatesMap.keySet()) {
                UserDormAssociate userDormAssociateOther = new UserDormAssociate();
                userDormAssociateOther.setUid(userId);
                userDormAssociateOther.setOrderId(orderId);
                userDormAssociateOther.setRoomName(allocatedRoom.getRoomName());
                userDormAssociateOther.setStuNo(stuNo);
                userDormAssociateOther.setCreateTime(new Date());
                userDormAssociateOther.setUpdateTime(new Date());
                userDormAssociateOther.setIsDel(0);
                affectedRows32 = userDormAssociateMapper.insertUseGeneratedKeys(userDormAssociateOther);
                if (affectedRows32 != 1) {
                    response.setCode(SysRetCodeConstants.ROOM_ADD_FAILURE.getCode());
                    response.setMsg(SysRetCodeConstants.ROOM_ADD_FAILURE.getMessage());
                    return response;
                }
            }


            if (affectedRows1 != 1 || affectedRows2 != 1 || affectedRows31 != 1) {
                response.setCode(SysRetCodeConstants.ROOM_ADD_FAILURE.getCode());
                response.setMsg(SysRetCodeConstants.ROOM_ADD_FAILURE.getMessage());
                return response;
            }

            //扣减宿舍容量
            Example buildingRoomExample = new Example(BuildingRoom.class);
            buildingRoomExample.createCriteria()
                    .andEqualTo("roomName", allocatedRoom.getRoomName())
                    .andEqualTo("isDel", 0);
            List<BuildingRoom> buildingRooms = buildingRoomMapper.selectByExample(buildingRoomExample);
            if (buildingRooms == null || buildingRooms.size() != 1) {
                response.setCode(SysRetCodeConstants.DB_EXCEPTION.getCode());
                response.setMsg(SysRetCodeConstants.DB_EXCEPTION.getMessage());
                return response;
            }
            BuildingRoom buildingRoom = new BuildingRoom();
            buildingRoom.setEmptyNo(buildingRooms.get(0).getEmptyNo() - teammatesMap.size() - 1);
            int affectedRow4 = buildingRoomMapper.updateByExampleSelective(buildingRoom, buildingRoomExample);
            if (affectedRow4 != 1) {
                response.setCode(SysRetCodeConstants.ROOM_EMPTY_BED_REDUCE_FAILURE.getCode());
                response.setMsg(SysRetCodeConstants.ROOM_EMPTY_BED_REDUCE_FAILURE.getMessage());
                return response;
            }

            //同时修改userInfo的isChosen信息
            userInfoExample.createCriteria()
                    .andEqualTo("stuNo", selfStudentNo)
                    .andEqualTo("isDeleted", 0);
            UserInfo userInfoSelf = new UserInfo();
            userInfoSelf.setIsChosen(1);
            int affectedRows5 = userInfoMapper.updateByExampleSelective(userInfoSelf, userInfoExample);
            if (affectedRows5 != 1) {
                response.setCode(SysRetCodeConstants.DB_EXCEPTION.getCode());
                response.setMsg(SysRetCodeConstants.DB_EXCEPTION.getMessage());
                return response;
            }

            for (String stuNo : teammatesMap.keySet()) {
                Example otherUserInfoExample = new Example(UserInfo.class);
                otherUserInfoExample.createCriteria()
                        .andEqualTo("stuNo", stuNo)
                        .andEqualTo("isDeleted", 0);
                UserInfo userInfoOther = new UserInfo();
                userInfoOther.setIsChosen(1);
                int affectedRows6 = userInfoMapper.updateByExampleSelective(userInfoOther, otherUserInfoExample);
                if (affectedRows6 != 1) {
                    response.setCode(SysRetCodeConstants.DB_EXCEPTION.getCode());
                    response.setMsg(SysRetCodeConstants.DB_EXCEPTION.getMessage());
                    return response;
                }
            }

            //返回值处理,如果程序走到此处，说明以上所有检测与数据库操作全部成功
            response.setOrderId(orderId);
            response.setCode(SysRetCodeConstants.SUCCESS.getCode());
            response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());

        } catch (Exception e) {
            log.info(e.getMessage());
            response.setCode(SysRetCodeConstants.SYSTEM_ERROR.getCode());
            response.setMsg(SysRetCodeConstants.SYSTEM_ERROR.getMessage());
        }
        return response;
    }

    private void requestCheck(Map<String, Object> request) {

    }
}
